package com.xygz.orm;

import com.xiyuan.smartutils.paging.PageResult;
import com.xygz.orm.exception.ORMException;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;

/**
 * DML英文全称是Data Manipulation Language(数据操作语言)，用来对数据库中表的数据记录进 行增、删、改操作。 添加数据（INSERT） 修改数据（UPDATE） 删除数据（DELETE)
 *
 * @author xiyuan-lgz 2023-09-19 @version v1.0.0 新建与整理
 */
@SuppressWarnings("all")
public interface DML {
    
    /**
     * 增加数据,传入标准[表类]对象
     *
     * @param data              数据列表
     * @return                  返回 true|false, true=插入成功
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public <E> boolean insert(E data) throws ORMException, SQLException;
    
    /**
     * 批量增加数据,默认根据默认会返回自增主键
     *
     * @param list              表对象列表
     * @return                  返回 true|false, true=插入成功
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public <E> boolean[] insertBatch(Collection<E> list) throws ORMException, SQLException;
    
    
    /**
     * 批量增加数据
     *
     * @param list              表对象列表
     * @param batchSize         批次大小
     * @return                  返回 true|false, true=插入成功
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public default  <E> boolean[] insertBatch(Collection<E> list, int batchSize) throws SQLException, ORMException{
        return insertBatch(list, true, batchSize);
    }
    
    /**
     * 批量增加数据，手动确定是否自动绑定自增主键。
     *
     * @param list              表对象列表
     * @param useGeneratedKeys  手动确定是否自动绑定自增主键。true = 表自动设置，false=不自动设置
     * @return                  返回 true|false, true=插入成功
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public <E> boolean[] insertBatch(Collection<E> list, boolean useGeneratedKeys) throws ORMException, SQLException;
    
    /**
     * 批量增加数据，手动确定是否自动绑定自增主键。
     *
     * @param list              表对象列表
     * @param useGeneratedKeys  手动确定是否自动绑定自增主键。true = 表自动设置，false=不自动设置
     * @param batchSize         批次大小
     * @return                  返回 true|false, true=插入成功
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public <E> boolean[] insertBatch(Collection<E> list, boolean useGeneratedKeys, int batchSize) throws ORMException, SQLException;
    
    
    //
    // /**
    //  * 插入过着修改数据
    //  *
    //  * @param data              表对象
    //  * @param updater           更新器
    //  * @return                  表示插入的条数
    //  * @throws ORMException     ORM异常
    //  * @throws SQLException     数据库异常
    //  */
    // public <E> int insertOrUpdate(E data, Updater<E> updater) throws ORMException, SQLException;
    //
    //
    // /********************************************************************************************/
    // // replace 替换数据，MYSQL支持，如果有数据先删除后增加
    // /********************************************************************************************/
    //
    // /**
    //  * 替换数据,传入标准[表类]对象
    //  *
    //  * @param data              数据对象
    //  * @return                  表示插入的条数
    //  * @throws ORMException     ORM异常
    //  * @throws SQLException     数据库异常
    //  */
    // public <E> int replace(E data) throws ORMException, SQLException;
    //
    //
    // /**
    //  * 批量替换数据
    //  *
    //  * @param dataList          表对象列表
    //  * @return                  表示插入的条数
    //  * @throws ORMException     ORM异常
    //  * @throws SQLException     数据库异常
    //  */
    // public int[] replaceBatch(List<?> dataList) throws ORMException, SQLException;
    //
    
    
    
    
    /********************************************************************************************/
    // delete 删除数据
    /********************************************************************************************/
    
    /**
     * 通过主键删除数据，批量删除， 如果表存在多主键，请使用 {@link DML#delete(Selector)}
     *
     * @param cls 表类
     * @param id                主键值
     * @param ids               多主键值
     * @return                  返回删除数
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public <T> long delete(Class<T> cls, Serializable id, Serializable... ids) throws ORMException, SQLException;
    
    /**
     * 删除数据根据条件，如果查询器条件为空则会抛异常，此方法不能全表删除。如果需要全表删除则使用 truncate 方法
     *
     * @param selector          查询器
     * @return                  返回删除数
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public <T> long delete(Selector<T> selector) throws ORMException, SQLException;
    
    /**
     * 批量删除数据，根据主键删除
     *
     * @param cls               表名
     * @param ids               关键属性为数组的列表，多个主键列表
     * @return                  返回删除结果数组
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public <T> long delete(Class<T> cls, Collection<Serializable> ids) throws ORMException, SQLException;
    
    /**
     * 清空表
     * @param cls               表类
     * @throws SQLException     数据库异常
     */
    public <T> void truncate(Class<T> cls) throws  ORMException, SQLException;
    /**
     * 清空表
     * @param tableName         数据库表名
     * @throws SQLException     数据库异常
     */
    public void truncate(String tableName) throws  ORMException, SQLException;
    /********************************************************************************************/
    // update 更新数据
    /********************************************************************************************/
    
    /**
     * 更新器更新数据
     *
     * @param updater           修改器
     * @return                  返回更新条目
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public <E> long update(Updater<E> updater) throws ORMException, SQLException;
    
    


    /**
     * 通过主键更新数据
     *
     * @param data              表对象
     * @param filterEmpty       是否过滤空内容, 包括 null 和 空字符串
     * @return                  更新的条数
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public default <E> long update(E data, boolean filterEmpty) throws ORMException, SQLException {
        return this.update(Updater.of(data).setFilterEmptyOrNull(filterEmpty));
    }

    /**
     * 更新数据，指定对象，根据主键进行更新，主键值和null空字符串值不更新
     *
     * @param data              表对象
     * @return                  更新的条数
     * @throws ORMException     ORM异常
     * @throws SQLException     数据库异常
     */
    public default <E> long update(E data) throws ORMException, SQLException {
        return this.update(Updater.of(data).setFilterEmptyOrNull(true));
    }
}
